package cz.zcu.fav.ratdroid.activity;

import org.joda.time.LocalDateTime;

import cz.zcu.fav.ratdroid.R;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.widget.Toast;
import cz.zcu.fav.ratdroid.activity.calendar.CalendarActivity;
import cz.zcu.fav.ratdroid.activity.calendar.day.DayActivity;
import cz.zcu.fav.ratdroid.activity.calendar.provider.ICalendarDataProvider;
import cz.zcu.fav.ratdroid.activity.calendar.provider.PersonalCalendarDataProvider;
import cz.zcu.fav.ratdroid.activity.calendar.reservation.CreatePickUpReservationActivity;
import cz.zcu.fav.ratdroid.bean.Object;
import cz.zcu.fav.ratdroid.bean.Properties;
import cz.zcu.fav.ratdroid.bean.Reservations;
import cz.zcu.fav.ratdroid.bean.User;
import cz.zcu.fav.ratdroid.service.IRestListener;
import cz.zcu.fav.ratdroid.service.RestService;
import cz.zcu.fav.ratdroid.service.RestTaskFactory;

/**
 * Main menu activity
 * 
 * @author Lukas Gemela
 * 
 */
public class MenuActivity extends SkeletonRestActivity<User>
{
	private static boolean invalidate = true;
	private static boolean configLoaded = false;
	public static String CALENDAR_GENERAL_PREFERENCES = "calendar.preferences";
	public static String MINIMUM_PERIOD_DURATION = "period.duration.minimum";
	public static String MAXIMUM_PERIOD_DURATION = "period.duration.maximum";
	public static String MAXIMUM_RESERVATION_PERIODICITY = "reservation.maximum.periodicity";

	private static SharedPreferences.OnSharedPreferenceChangeListener listener = null;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.menu);
		registerForContextMenu(findViewById(R.id.objectBrowserButton));

		// static listener on app settings
		if (listener == null)
		{
			listener = new SharedPreferences.OnSharedPreferenceChangeListener()
			{

				public void onSharedPreferenceChanged(
						SharedPreferences sharedPreferences, String key)
				{
					// app settings has changed so we need to relalidate our
					// session
					invalidate = true;
				}
			};

			PreferenceManager.getDefaultSharedPreferences(this)
					.registerOnSharedPreferenceChangeListener(listener);
		}

		validateSettings();
	}

	/**
	 * In case when app settings has been changed by user we need to revalidate
	 * the whole session
	 */
	private void validateSettings()
	{
		if (invalidate)
		{
			SharedPreferences pref = PreferenceManager
					.getDefaultSharedPreferences(this);
			String userName = pref.getString(
					SettingsActivity.KEY_PREF_USERNAME, null);

			// Clearing cookie is superimportant in cases when some other user
			// wants to login on phone
			if (pref.contains(RestTaskFactory.REST_COOKIE_KEY))
			{
				pref.edit().remove(RestTaskFactory.REST_COOKIE_KEY).apply();
			}
			setRestTask(RestService.getInstance().login(userName, this, this));
		}
	}

	public void buttonOnClick(View v)
	{
		switch (v.getId())
		{
		case R.id.favouritesButton:
			Intent fav = new Intent(this, FavouritesActivity.class);
			startActivity(fav);
			break;
		case R.id.settingsButton:
			Intent k = new Intent(this, SettingsActivity.class);
			startActivity(k);
			break;
		case R.id.calendarButton:
			Intent cal = new Intent(this, CalendarActivity.class);
			// hook corresponding calendar data provider
			cal.putExtra(
					ICalendarDataProvider.CALENDAR_DATA_PROVIDER_IDENTIFIER,
					new PersonalCalendarDataProvider());
			startActivity(cal);
			break;
		case R.id.objectBrowserButton:
			Intent obj = new Intent(this, ObjectBrowserActivity.class);
			startActivityForResult(obj,
					ObjectBrowserActivity.OBJECT_BROWSER_REQUEST_CODE);
			break;
		case R.id.returnItBackButton:
			Intent rtib = new Intent(this, ReturnItBackActivity.class);
			startActivity(rtib);
			break;
		case R.id.pickUpButton:
			Intent bro = new Intent(this, ObjectBrowserActivity.class);
			startActivityForResult(
					bro,
					CreatePickUpReservationActivity.PICK_UP_ACTIVITY_REQUEST_CODE);
			break;
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data)
	{
		if (requestCode == ObjectBrowserActivity.OBJECT_BROWSER_REQUEST_CODE)
		{
			if (resultCode == RESULT_OK)
			{
				Object result = (Object) data
						.getSerializableExtra(Object.SINGLE_OBJECT_IDENTIFIER);
				Intent intent = new Intent(this, ObjectProfileActivity.class);
				intent.putExtra(Object.SINGLE_OBJECT_IDENTIFIER, result);
				startActivity(intent);
			}
		} else if (requestCode == CreatePickUpReservationActivity.PICK_UP_ACTIVITY_REQUEST_CODE)
		{
			// as a result from object browser we need to be sure that selected
			// object is actually pickable
			if (resultCode == RESULT_OK)
			{
				final Object result = (Object) data
						.getSerializableExtra(Object.SINGLE_OBJECT_IDENTIFIER);
				if (!result.isPickable())
				{
					Toast.makeText(this, getString(R.string.notPickable),
							Toast.LENGTH_SHORT).show();
					return;
				}
				setRestTask(RestService.getInstance().pickUpObject(
						result.getId(), this, new IRestListener<Reservations>()
						{
							public void notifyDataLoaded(Reservations data)
							{
								if (!data.getReservations().isEmpty())
								{
									runOnUiThread(new Runnable()
									{
										public void run()
										{

											Toast.makeText(
													MenuActivity.this,
													MenuActivity.this
															.getString(R.string.reservationPicked),
													Toast.LENGTH_SHORT).show();
										}
									});
								} else
								{
									// ok there is no corresponding reservation
									// around, so lets create a new one
									Intent intent = new Intent(
											MenuActivity.this,
											CreatePickUpReservationActivity.class);
									intent.putExtra(
											Object.SINGLE_OBJECT_IDENTIFIER,
											result);
									LocalDateTime selectedTime = LocalDateTime
											.now();
									intent.putExtra(
											DayActivity.PRESELECTED_DATETIME,
											selectedTime);
									startActivity(intent);
								}
							}

							public void notifyException(final Exception ex)
							{
								runOnUiThread(new Runnable()
								{

									public void run()
									{
										Toast.makeText(MenuActivity.this,
												ex.getMessage(),
												Toast.LENGTH_SHORT).show();
									}
								});
							}
						}));
			}
		}
	}

	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo)
	{
		super.onCreateContextMenu(menu, v, menuInfo);
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.object_browser_menu, menu);

	}

	public void notifyDataLoaded(User data)
	{
		super.notifyDataLoaded(data);
		if (data != null)
		{
			invalidate = false;
			enableButtons(true);
			getSharedPreferences(User.SINGLE_USER_IDENTIFIER, MODE_PRIVATE)
					.edit().putInt(User.USER_ID, data.getId())
					.putString(User.USER_NAME, data.getName())
					.putString(User.USER_EMAIL, data.getEmail()).apply();
			Toast.makeText(this,
					getString(R.string.validLogin) + " " + data.getName(),
					Toast.LENGTH_SHORT).show();

			/**
			 * in case when settings is not loaded yet (it can happen on the
			 * very first start of app) we must load it from RAT server and
			 * store to app context
			 */
			if (!configLoaded)
			{
				final SharedPreferences pref = getSharedPreferences(
						CALENDAR_GENERAL_PREFERENCES, MODE_PRIVATE);
				if (!pref.contains(MINIMUM_PERIOD_DURATION)
						|| !pref.contains(MAXIMUM_PERIOD_DURATION)
						|| !pref.contains(MAXIMUM_RESERVATION_PERIODICITY))
				{
					// we are missing some preferences so lets download them
					setRestTask(RestService.getInstance().loadProperties(this,
							new IRestListener<Properties>()
							{

								public void notifyDataLoaded(Properties data)
								{
									configLoaded = true;
									pref.edit()
											.putLong(MINIMUM_PERIOD_DURATION,
													data.getMinimumDuration())
											.putLong(MAXIMUM_PERIOD_DURATION,
													data.getMinimumDuration())
											.putInt(MAXIMUM_RESERVATION_PERIODICITY,
													data.getMaximumPeriodsCount())
											.apply();
								}

								public void notifyException(Exception ex)
								{
									MenuActivity.super.notifyException(ex);
								}
							}));
				} else
				{
					configLoaded = true;
				}

			}

		}
	}

	@Override
	protected void onResume()
	{
		super.onResume();
		validateSettings();
	}

	/**
	 * enable or disable all buttons which underlying activities requires
	 * communication
	 * 
	 * @param enable
	 */
	private void enableButtons(boolean enable)
	{
		findViewById(R.id.favouritesButton).setEnabled(enable);
		findViewById(R.id.calendarButton).setEnabled(enable);
		findViewById(R.id.objectBrowserButton).setEnabled(enable);
		findViewById(R.id.returnItBackButton).setEnabled(enable);
		findViewById(R.id.pickUpButton).setEnabled(enable);
	}

	public void notifyException(Exception ex)
	{
		setRestTask(null);
		runOnUiThread(new Runnable()
		{
			public void run()
			{
				enableButtons(false);
				Toast.makeText(MenuActivity.this,
						getString(R.string.notValidLogin), Toast.LENGTH_SHORT)
						.show();
				invalidate = true;
				RestTaskFactory.clear();
			}
		});

	}

}
